﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.FrameWork.Commons.Hepler
{
    /// <summary>
    /// 上传文件委托配置类，配置的委托将用于全局
    /// </summary>
    public class UploadHelp
    {
        /// <summary>
        /// 文件上传本地路径委托
        /// </summary>
        private static Func<byte[], string, UploadFileType, Task<string>> func = null;

        /// <summary>
        /// 文件上传Azure委托
        /// </summary>
        private static Func<byte[], string, UploadFileType, Task<string>> funcBlob = null;

        /// <summary>
        /// 分片上传--云存储
        /// </summary>
        private static Func<byte[], string, UploadFileType, Task<string>> _funcBlobBlack = null;
        /// <summary>
        /// 分片上传--本地
        /// </summary>
        private static Func<byte[], string, UploadFileType, Task<string>> _funcLocationBlack = null;
        /// <summary>S
        /// 合并分片--云存储
        /// </summary>
        private static Func<List<string>, string, string, UploadFileType, Task<string>> _mergeBlobBlack = null;
        /// <summary>
        /// 合并分片--本地
        /// </summary>
        private static Func<List<string>, string, string, UploadFileType, Task<string>> _mergeLocationBlack = null;


        /// <summary>
        /// 默认上传方式
        /// </summary>
        private static UploadFunEnum defaultFuncEnum;
        /// <summary>
        /// 默认分片上传方式
        /// </summary>
        private static UploadFunEnum defaultBlackEnum;

        /// <summary>
        /// 初始化委托
        /// </summary>
        /// <param name="_func"></param>
        public static void Init(Func<byte[], string, UploadFileType, Task<string>> _func, UploadFunEnum funcEnum = UploadFunEnum.location)
        {
            switch (funcEnum)
            {
                case UploadFunEnum.location:
                    func = _func;
                    break;
                case UploadFunEnum.blob:
                    funcBlob = _func;
                    break;
                case UploadFunEnum.LocationBlack:
                    _funcLocationBlack = _func;
                    break;
                case UploadFunEnum.BlobBlack:
                    _funcBlobBlack = _func;
                    break;
                case UploadFunEnum.defalut:
                    break;
            }
        }
        /// <summary>
        /// 合并分片内容的初始化委托
        /// </summary>
        /// <param name="_func"></param>
        /// <param name="funcEnum"></param>
        public static void InitMerge(Func<List<string>, string, string, UploadFileType, Task<string>> _func, UploadFunEnum funcEnum = UploadFunEnum.LocationBlack)
        {
            switch (funcEnum)
            {
                case UploadFunEnum.LocationBlack:
                    _mergeLocationBlack = _func;
                    break;
                case UploadFunEnum.BlobBlack:
                    _mergeBlobBlack = _func;
                    break;
            }
        }
        /// <summary>
        /// 初始化默认上传方式
        /// </summary>
        /// <param name="_defaultFuncEnum"></param>
        public static void InitDefaultUpload(UploadFunEnum _defaultFuncEnum)
        {
            defaultFuncEnum = _defaultFuncEnum;
            //是否为云存储，非云存储直接使用初始化本地分片上传
            defaultBlackEnum = _defaultFuncEnum == UploadFunEnum.blob ? UploadFunEnum.BlobBlack : UploadFunEnum.LocationBlack;
        }

        /// <summary>
        /// 通过委托上传文件
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="fileName">文件名</param>
        /// <param name="fileType">文件类型</param>
        /// <returns></returns>
        public static async Task<string> Execute(byte[] bytes, string fileName, UploadFileType fileType, UploadFunEnum funcEnum = UploadFunEnum.defalut)
        {

            if (func == null || funcBlob == null) throw new Exception("请先初始化上传委托");

            if (funcEnum == UploadFunEnum.defalut)//如果采用默认配置的上传方式
            {
                if (defaultFuncEnum == UploadFunEnum.location)
                {
                    return await func.Invoke(bytes, fileName, fileType);
                }
                else
                {
                    return await funcBlob.Invoke(bytes, fileName, fileType);
                }
            }
            else if (funcEnum == UploadFunEnum.location)//指定上传本地
            {
                return await func.Invoke(bytes, fileName, fileType);
            }
            else//指定上传Azure
            {
                return await funcBlob.Invoke(bytes, fileName, fileType);
            }

        }

        /// <summary>
        /// 分片上传处理
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="fileDir"></param>
        /// <param name="fileType"></param>
        /// <param name="funEnum"></param>
        /// <returns></returns>
        public static async Task<string> ExecuteBlack(byte[] bytes, string fileDir, UploadFileType fileType, UploadFunEnum funEnum = UploadFunEnum.defalut)
        {
            funEnum = funEnum == UploadFunEnum.defalut ? defaultBlackEnum : funEnum;
            if (funEnum != UploadFunEnum.BlobBlack && funEnum != UploadFunEnum.LocationBlack)
            {
                return await Execute(bytes, fileDir, fileType, funEnum);
            }

            if ((funEnum == UploadFunEnum.LocationBlack && (_funcLocationBlack == null || _mergeLocationBlack == null)) ||
                (funEnum == UploadFunEnum.BlobBlack && (_funcBlobBlack == null || _mergeBlobBlack == null)))
            {
                throw new Exception("请先初始化分片上传委托");
            }
            var result = string.Empty;
            if (funEnum == UploadFunEnum.LocationBlack)
            {
                result = await _funcLocationBlack.Invoke(bytes, fileDir, fileType);
            }
            else
            {
                result = await _funcBlobBlack.Invoke(bytes, fileDir, fileType);
            }

            return result;
        }

        /// <summary>
        /// 合并分片，本地存储开集群的模式下不建议开启分片上传
        /// </summary>
        /// <param name="fileDir"></param>
        /// <param name="fileName"></param>
        /// <param name="blockList"></param>
        /// <param name="fileType"></param>
        /// <param name="funEnum"></param>
        /// <returns></returns>
        public static async Task<string> MergeBlack(string fileDir, string fileName, List<string> blockList, UploadFileType fileType, UploadFunEnum funEnum = UploadFunEnum.defalut)
        {
            funEnum = funEnum == UploadFunEnum.defalut ? defaultBlackEnum : funEnum;
            if ((funEnum == UploadFunEnum.LocationBlack && (_funcLocationBlack == null || _mergeLocationBlack == null)) ||
                (funEnum == UploadFunEnum.BlobBlack && (_funcBlobBlack == null || _mergeBlobBlack == null)))
            {
                throw new Exception("请先初始化分片上传委托");
            }
            var result = string.Empty;
            if (funEnum == UploadFunEnum.LocationBlack)
            {
                result = await _mergeLocationBlack.Invoke(blockList, fileName, fileDir, fileType);
            }
            else
            {
                result = await _mergeBlobBlack.Invoke(blockList, fileName, fileDir, fileType);
            }

            return result;
        }

    }

    /// <summary>
    /// 文件枚举 
    /// </summary>
    public enum UploadFileType
    {
        [Description("Face")]
        Face = 1,
        [Description("Voice")]
        Voice = 2,
        [Description("Image")]
        Image = 3,
        [Description("Video")]
        Video = 4,
        [Description("File")]
        File = 5,
        [Description("QrCode")]
        QrCode = 6
    }

    public enum UploadFunEnum
    {
        defalut = 0,
        location = 1,//本地
        blob = 2,//Azure云上传
        /// <summary>
        /// 本地分片上传
        /// </summary>
        LocationBlack = 3,
        /// <summary>
        /// 云分片上传
        /// </summary>
        BlobBlack = 4
    }
    public enum BlobFileType
    {
        Face = 1,
        Voice = 2,
        Image = 3,
        Video = 4,
        File = 5,
        QrCode = 6,
        Poster = 7,
        IncreasePoster = 8,
        WxHeadImg = 9
    }
}

